//
// Name :        Model Viewer
// Written by :  Charles B. Owen
//               http://www.cse.msu.edu/~cbowen
//               Michigan State University
//               Copyright (c) 2011, Michigan State University
// Version :     1.00 09-26-2011
//

using System;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using System.Drawing;

namespace ModelViewer
{
    /// <summary>
    /// The main form for the program. 
    /// </summary>
    public partial class MainForm : Form, TreeViewer.IObserver
    {
        public enum Modes { None, Move, Rotate, Scale };

        #region Fields

        /// <summary>
        /// The program main settings
        /// </summary>
        private Settings settings = null;

        private MenuRenderer menuRenderer = null;


        private ColorTable colorTable = null;

        /// <summary>
        /// xmodl file format export dialog box
        /// </summary>
        private SaveFileDialog xmodlExportDlg = new SaveFileDialog();

        /// <summary>
        /// xmodl options dialog box
        /// </summary>
        private XmodlOptionsDlg xmodlOptionsDlg = new XmodlOptionsDlg();

        /// <summary>
        /// The actual xmodl options
        /// </summary>
        private XmodlOptions xmodlOptions = new XmodlOptions();

        /// <summary>
        /// xanal file format export dialog box
        /// </summary>
        private SaveFileDialog xanalExportDlg = new SaveFileDialog();

        /// <summary>
        /// Current mouse mode (future capability)
        /// </summary>
        private Modes mode = Modes.Rotate;

        #endregion

        #region Properties

        public Modes Mode
        {
            get { return mode; }
        }

        
        /// <summary>
        /// The program settings
        /// </summary>
        public Settings Settings { get { return settings; } }

        /// <summary>
        /// The model viewer control we use
        /// </summary>
        public ModelViewerControl ModelViewerControl { get { return modelViewerControl; } }

        public MenuRenderer MenuRenderer
        {
            get { return menuRenderer; }
        }

        public ColorTable ColorTable
        {
            get { return colorTable; }
        }

        #endregion


        /// <summary>
        /// Constructs the main form.
        /// </summary>
        public MainForm()
        {
            InitializeComponent();

            colorTable = new ColorTable();
            menuRenderer = new MenuRenderer(colorTable);

            menuStrip.Renderer = menuRenderer;
            toolStrip1.Renderer = new ToolbarRenderer();

            modelViewerControl.MainForm = this;
            treeViewer.MainForm = this;

            // Tell the tree viewer about the models in the viewer
            treeViewer.Models = modelViewerControl.Models;

            // Tell components about the tree viewer so they can 
            // register themselves as observers
            adjustControls.TreeViewer = treeViewer;
            timeLine.TreeViewer = treeViewer;
            animTab.TreeViewer = treeViewer;

            // Add ourselves as an observer of the treeviewer
            treeViewer.AddObserver(this);

            SetUI();

            BoundingBoxRenderer.Instance.Enabled = boundingBoxToolStripMenuItem.Checked;
        }

        public void UpdateObserver()
        {
            SetUI();
        }


        private void OnLoad(object sender, EventArgs e)
        {
            settings = new Settings();
            settings.Reload();

            this.Size = settings.FormSize;
        }

        private void OnClosing(object sender, FormClosingEventArgs e)
        {
            settings.FormSize = this.Size;
            settings.Save();
        }

        private void SetUI()
        {
            moveToolStripMenuItem.Checked = mode == Modes.Move;
            rotateToolStripMenuItem.Checked = mode == Modes.Rotate;
            scaleToolStripMenuItem.Checked = mode == Modes.Scale;
            moveStripButton.Checked = mode == Modes.Move;
            rotateStripButton.Checked = mode == Modes.Rotate;
            scaleStripButton.Checked = mode == Modes.Scale;

            ViewerModel model = treeViewer.SelectedModel;
            bool selected = model != null;

            closeStripButton.Enabled = selected;
            closeToolStripMenuItem.Enabled = selected;
            exportXmodlFileToolStripMenuItem.Enabled = selected;
            exportXanalFileToolStripMenuItem.Enabled = selected;

            groupStatistics.Enabled = selected;

            if (selected)
            {
                labelVertices.Text = model.NumVertices.ToString("N0");
                labelTriangles.Text = model.NumTriangles.ToString("N0");
                labelEffects.Text = model.NumEffects.ToString("N0");
                labelMeshes.Text = model.NumMeshes.ToString("N0");
                labelMeshParts.Text = model.NumMeshParts.ToString("N0");
            }

            else
            {
                labelVertices.Text = "";
                labelTriangles.Text = "";
                labelEffects.Text = "";
                labelMeshes.Text = "";
                labelMeshParts.Text = "";
            }


        }

        /// <summary>
        /// Event handler for the Exit menu option.
        /// </summary>
        void ExitMenuClicked(object sender, EventArgs e)
        {
            Close();
        }


        /// <summary>
        /// Event handler for the Open menu option.
        /// </summary>
        void OpenMenuClicked(object sender, EventArgs e)
        {
            OpenFileDialog fileDialog = new OpenFileDialog();

            // Default to the directory which contains our content files.
            string assemblyLocation = Assembly.GetExecutingAssembly().Location;
            string relativePath = Path.Combine(assemblyLocation, "../../../../Content");
            string contentPath = Path.GetFullPath(relativePath);

            fileDialog.InitialDirectory = contentPath;

            fileDialog.Title = "Load Model";

            fileDialog.Filter = "Model Files (*.fbx;*.x)|*.fbx;*.x|" +
                                "FBX Files (*.fbx)|*.fbx|" +
                                "X Files (*.x)|*.x|" +
                                "All Files (*.*)|*.*";

            if (fileDialog.ShowDialog() == DialogResult.OK)
            {
                LoadModel(fileDialog.FileName);
                SetUI();
            }
        }


        /// <summary>
        /// Loads a new 3D model file into the ModelViewerControl.
        /// </summary>
        void LoadModel(string fileName)
        {
            BuildDlg buildDlg = new BuildDlg(this, fileName, modelViewerControl);
            buildDlg.ShowDialog(this);

            treeViewer.Build();
        }



        private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OptionsDlg dlg = new OptionsDlg();
            dlg.BackgroundColor = settings.BackgroundColor;
            dlg.AxisColorX = settings.AxisColorX;
            dlg.AxisColorY = settings.AxisColorY;
            dlg.AxisColorZ = settings.AxisColorZ;
            dlg.AmbientColor = settings.AmbientColor;
            if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                settings.AmbientColor = dlg.AmbientColor;
                settings.AxisColorX = dlg.AxisColorX;
                settings.AxisColorY = dlg.AxisColorY;
                settings.AxisColorZ = dlg.AxisColorZ;
                settings.BackgroundColor = dlg.BackgroundColor;
                settings.Save();
            }
        }

        private void openToolStripButton_Click(object sender, EventArgs e)
        {

        }


        private void moveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mode = Modes.Move;
            SetUI();
        }

        private void rotateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mode = Modes.Rotate;
            SetUI();
        }

        private void scaleToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mode = Modes.Scale;
            SetUI();
        }

        private void CloseMenuClicked(object sender, EventArgs e)
        {
            if (treeViewer.SelectedModel == null)
                return;

            modelViewerControl.RemoveModel(treeViewer.SelectedModel);
            treeViewer.Build();
        }


        private void OnSeparatorPaint(object sender, PaintEventArgs e)
        {

        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutDlg dlg = new AboutDlg(modelViewerControl);
            dlg.ShowDialog();
        }

        /// <summary>
        /// Export the current model in the xmodl XML format
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void exportXmodlFileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //
            // Get any options
            //
            xmodlOptionsDlg.Options = xmodlOptions;
            if (xmodlOptionsDlg.ShowDialog() != DialogResult.OK)
                return;

            xmodlOptions = xmodlOptionsDlg.Options;

            //
            // Get the filename
            //
            xmodlExportDlg.Title = "Export Model";

            xmodlExportDlg.Filter = "Model Files (*.xmodl)|*.xmodl|" +
                                "All Files (*.*)|*.*";

            if (xmodlExportDlg.ShowDialog() != DialogResult.OK)
                return;

            ExportModel(xmodlExportDlg.FileName, xmodlOptions);
        }

        /// <summary>
        /// Actually export the model with the supplied name and options
        /// </summary>
        /// <param name="fileName"></param>
        private void ExportModel(string fileName, XmodlOptions options)
        {
            if (treeViewer.SelectedModel == null)
                return;

            Cursor.Current = Cursors.WaitCursor;
            ModelExporter exporter = new ModelExporter(treeViewer.SelectedModel);
            exporter.Export(fileName, options);
            Cursor.Current = Cursors.Default;
        }
        
        
        private void exportXanalFileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //
            // Get any options
            //
            xmodlOptionsDlg.Options = xmodlOptions;
            if (xmodlOptionsDlg.ShowDialog() != DialogResult.OK)
                return;

            xmodlOptions = xmodlOptionsDlg.Options;

            //
            // Get the filename
            //
            xanalExportDlg.Title = "Export Animation";

            xanalExportDlg.Filter = "Xmodl Animation Files (*.xanal)|*.xanal|" +
                                "All Files (*.*)|*.*";

            if (xanalExportDlg.ShowDialog() != DialogResult.OK)
                return;

            ExportAnimation(xanalExportDlg.FileName, xmodlOptions);
        }


        /// <summary>
        /// Actually export the animation with the supplied name and options
        /// </summary>
        /// <param name="fileName"></param>
        private void ExportAnimation(string fileName, XmodlOptions options)
        {
            if (treeViewer.SelectedModel == null)
                return;

            Cursor.Current = Cursors.WaitCursor;
            AnimationExporter exporter = new AnimationExporter();
            exporter.Export(treeViewer, fileName, options);
            Cursor.Current = Cursors.Default;
        }
        

        /// <summary>
        /// Handle drag/drop of FBX file onto the program.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void modelViewerControl_DragDrop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop, true))
            {
                string[] droppedFilePaths = e.Data.GetData(DataFormats.FileDrop, true) as string[];
                if (droppedFilePaths.Length > 0)
                {
                    var fileName = droppedFilePaths[0];
                    LoadModel(fileName);
                    SetUI();
                }

            }
        }

        private void modelViewerControl_DragEnter(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Copy;
        }

        private void boundingBoxToolStripMenuItem_Click(object sender, EventArgs e)
        {
            boundingBoxToolStripMenuItem.Checked = !boundingBoxToolStripMenuItem.Checked;
            BoundingBoxRenderer.Instance.Enabled = boundingBoxToolStripMenuItem.Checked;
        }



    }
}
